package com.youdianstar.app.ui

import android.app.Activity
import android.app.Dialog
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.text.Html
import android.view.View
import android.widget.CompoundButton
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.youdianstar.app.common.BisType
import com.youdianstar.app.common.ConfigKey

import com.youdianstar.app.R
import com.youdianstar.app.BR
import com.youdianstar.app.databinding.ActivityRentPlanBinding

import com.youdianstar.app.common.Extra
import com.youdianstar.app.common.PRIVACY_URL
import com.youdianstar.app.common.TERM_URL
import com.youdianstar.app.common.HTTP_BRS_URL
import com.youdianstar.app.common.Language
import com.youdianstar.app.common.base.BaseActivity
import com.youdianstar.app.common.ex.setThrottleListener
import com.youdianstar.app.common.network.BaseApiResultObserver
import com.youdianstar.app.common.util.StrUtil
import com.youdianstar.app.entity.RentResult
import com.youdianstar.app.util.AppDialogUtil

import com.youdianstar.app.common.auko.startActivity
import com.youdianstar.app.common.ex.setAgreementLine
import com.youdianstar.app.common.util.LanguageConfig
import com.youdianstar.app.common.util.LogUtil
import com.youdianstar.app.common.util.MathUtil
import com.youdianstar.app.common.widget.ClickURLSpan
import com.youdianstar.app.entity.CardBindReq
import com.youdianstar.app.entity.CardEntity
import com.youdianstar.app.entity.RentalAuthRequest
import com.youdianstar.app.entity.RentalAuthRes
import com.youdianstar.app.entity.WalletInfo
import com.youdianstar.app.support.imp.ICardPayListener
import com.youdianstar.app.ui.pay.PaymentCodeActivity
import com.youdianstar.app.ui.web.WebActivity
import com.youdianstar.app.util.DataAppManager
import com.youdianstar.app.util.SheetPaymentDialog
import com.youdianstar.app.util.WalletDialogUtil
import com.youdianstar.app.util.initGoogleMethodLauncher
import com.youdianstar.app.util.initStripe
import com.youdianstar.app.util.onPaymentMethodResult
import com.youdianstar.app.util.startGooglePayment
import com.stripe.android.ApiResultCallback
import com.stripe.android.PaymentIntentResult
import com.stripe.android.Stripe
import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher
import com.stripe.android.model.CardParams
import com.stripe.android.model.ConfirmPaymentIntentParams
import com.stripe.android.model.PaymentMethodCreateParams
import com.stripe.android.model.StripeIntent
import com.stripe.android.model.Token
import com.stripe.android.stripecardscan.cardscan.CardScanSheet
import org.koin.androidx.viewmodel.ext.android.viewModel
import java.util.Locale


/**
 * File: PricePlanActivity
 * Author: 82149 Create: 2021/11/16 17:22
 * Changes (from 2021/11/16)
 * --------------------------------------------------
 * description: 计费规则显示页面 弹框 毛玻璃背景
 * ---------------------------------------------------
 *
 */
class RentPlanActivity : BaseActivity<ActivityRentPlanBinding, ScanViewModel>() {

    override fun layoutId(): Int = R.layout.activity_rent_plan

    override fun initVariableId(): Int = BR.viewModel

    override fun initViewModel(): ScanViewModel {
        val model: ScanViewModel by viewModel()
        return model
    }

    private val mHandler = Handler(Looper.myLooper()!!)
    //机柜编号
    private var snoNo: String? = null
    private var planText: String? = null
    private var branchNameText: String? = null

    //租借条件: 1-白名单, 2-有押金, 3-已授权
    private var rentAvailableStatus: Int = -1
    //需要 预授权金额
    private var preAuthAmount: Double = 0.0
    //需要 预付款金额
    private var prepaymentAmount: Double = 0.0
    //本地上次租借的付款类型
    private var lastPayType = 0
    //接口返回的租借类型
    private var rentType: Int = 0 //1.卡预授权 2.预授权谷歌支付

    //判断授权状态
    private var isCheckPreStatus = false
    private var preSelectDialog: Dialog? = null

    //stripeGoogle
    private var stripe: Stripe? = null
    private var googleMethodLauncher: GooglePayPaymentMethodLauncher? = null
    private var cardPayParams: PaymentMethodCreateParams? = null
    private var cardPayDialog: SheetPaymentDialog? = null
    private var stripeScanSheet: CardScanSheet? = null
    private var isGoogleReady = false
    private var countryTx: String = "" //国家代码
    private var currencyTx: String = "" //货币代码

    //租借下单单号
    private var orderNo: String? = null
    //租借接口成功
    private var rentItSuccess = false
    //提示展示完2秒
    private var hintCountShow = false

    private val mPaymentLauncher: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult(),
        object : ActivityResultCallback<ActivityResult> {
            override fun onActivityResult(result: ActivityResult) {
                result.let { res ->
                    if (res.resultCode == Activity.RESULT_OK) {
                        startRentActivityByDirect()
                    }
                }
            }
        })

    override fun initData() {
        super.initData()
        mBinding.headBar.initTitle(this, title = "", showInner = false)
        stripe = initStripe(this)
        countryTx = DataAppManager.instance.countryTx()
        currencyTx = DataAppManager.instance.currencyTx()
        googleMethodLauncher = initGoogleMethodLauncher(this, countryCode = countryTx,
            readyCallback = { isReady ->
                LogUtil.d("---Pay google ready: $isReady")
                isGoogleReady = isReady
            }, resultCallback = object : GooglePayPaymentMethodLauncher.ResultCallback {
                override fun onResult(result: GooglePayPaymentMethodLauncher.Result) {
                    onPaymentMethodResult(result, onPaySuccess = { paymentMethodId ->
                        if (!StrUtil.isEmpty(paymentMethodId)) {
                            requestGoogleAuth(paymentMethodId)
                        }
                    }, onPayError = { msg ->
                        if (msg == "AT-canceled") {
                            toastShow(getString(R.string.public_cancel), type = 3)
                        } else {
                            toastShow(msg)
                        }
                    })
                }
            })

        rentAvailableStatus = intent.getIntExtra(Extra.IT_TYPE, -1)
        preAuthAmount = intent.getDoubleExtra(Extra.IT_AMOUNT, 0.0)
        prepaymentAmount = intent.getDoubleExtra(Extra.IT_PREAMOUNT, 0.0)
        lastPayType = DataAppManager.instance.getLastPayType()

        snoNo = intent.getStringExtra(Extra.IT_SNO)
        planText = intent.getStringExtra(Extra.IT_DATA)
        branchNameText = intent.getStringExtra(Extra.IT_MSG)

        mBinding.tvPlanContent.text = planText ?: ""
        mBinding.ivMark.setImageResource(R.mipmap.mark_map_selected_on)
        mBinding.tvBranchName.text = branchNameText ?: ""
        //mBinding.clBranchInfo.visibility = if (StrUtil.isEmpty(branchNameText)) View.INVISIBLE else View.VISIBLE
        mBinding.clBranchInfo.visibility = View.GONE //250228 不显示网点了
        //预授权文本
        val symbolTx = DataAppManager.instance.symbolTx()
        val preAuthTx = symbolTx + MathUtil.round(preAuthAmount)
        mBinding.tvPreAuthAmount.text = preAuthTx
        mBinding.tvPreText.text = String.format(getString(R.string.wallet_frozeTips), preAuthTx)
        //协议下划线 - 预授权(250228 改用户协议)
        val agreeContent = Html.fromHtml(getString(R.string.rent_agree_Html))
        mBinding.tvAgreeContent.text = agreeContent
        ClickURLSpan.textUnderline(mBinding.tvAgreeContent, R.color.color_66666B) {
            val langParam = getAgreementLangParam()
            if (it == TERM_URL) {
                val termsUrl = "${HTTP_BRS_URL}/sw/app/agreement/user.html?lang=$langParam"
                startActivity<WebActivity>(Extra.IT_DATA to termsUrl, Extra.IT_NOTIFY to getString(R.string.login_termOfUse))
            }
        }

        mBinding.boxAgree.isChecked = true
        mBinding.boxAgree.setOnCheckedChangeListener(object : CompoundButton.OnCheckedChangeListener {
            override fun onCheckedChanged(button: CompoundButton?, isCheck: Boolean) {
                mBinding.btnConfirm.isEnabled = isCheck
            }
        })
    }

    override fun initLiveObserver() {
        super.initLiveObserver()
        mViewModel.rentResultLiveData.observe(this, object : BaseApiResultObserver<RentResult>(false) {
                override fun onDataResult(data: RentResult?) {
                    super.onDataResult(data)
                    dismissDialog()
                    data?.let {
                        orderNo = it.orderNo
                        rentItSuccess = true
                        if (hintCountShow) {
                            startRentActivity() //加载提示2秒-跳转页面
                        }
                    }
                }

                override fun onNetError(code: Int, e: String?) {
                    super.onNetError(code, e)
                    dismissDialog()
                    rentItSuccess = false
                    if (hintCountShow) {
                        AppDialogUtil.instance.cleanHintDialog()
                        toastShow(e)
                    } else {
                        mHandler.removeCallbacksAndMessages(null)
                        mHandler.postDelayed({
                            AppDialogUtil.instance.cleanHintDialog()
                            toastShow(e)
                        }, 800L)
                    }
                }
            })

        mViewModel.rentAuthResultLiveData.observe(this, object : BaseApiResultObserver<RentalAuthRes>(false) {
                override fun onDataResult(data: RentalAuthRes?) {
                    super.onDataResult(data)
                    dismissDialog()
                    data?.let { netIt ->
                        netIt.order?.let { or ->
                            orderNo = or.orderNo
                        }
                        rentType = netIt.rentType
                        if (rentType == 2){
                            lastPayType = 1
                        }

                        if (netIt.scene == 1) {
                            if (isCheckPreStatus) {
                                //第一次授权检查
                                isCheckPreStatus = false
                                if (netIt.preAuthAmount > 0){
                                    preAuthAmount = netIt.preAuthAmount
                                }
                                snoNo?.let {
                                    mViewModel.getWallet(true)
                                }
                            } else {
                                if (null != netIt.resp) {
                                    if (netIt.resp.status == 11){ //已授权过
                                        startRentActivityByDirect()
                                    }else{
                                        netIt.resp.let { rsp ->
                                            if (rsp.displayMode == "app" && rsp.displayContent.isNotEmpty()) {
                                                requestAppPayment(rsp.displayContent, cardPayParams) {
                                                    showLoadingDialog("")
                                                }
                                            }
                                        }
                                    }
                                } else {
                                    toastShow(getString(R.string.home_failed))
                                }
                            }
                        } else {
                            isCheckPreStatus = false
                            startRentActivityByDirect()
                        }
                    }
                }

                override fun onNetError(code: Int, e: String?) {
                    super.onNetError(code, e)
                    dismissDialog()
                    toastShow(e)
                }
            })

        mViewModel.walletNetLiveData.observe(this, object : BaseApiResultObserver<WalletInfo>(false) {
            override fun onDataResult(data: WalletInfo?) {
                super.onDataResult(data)
                dismissDialog()
                data?.let {
                    if (it.requirePrepaymentAmount > 0){
                        prepaymentAmount = it.requirePrepaymentAmount
                    }
                    snoNo?.let { sn ->
                        if (it.cardList.isNullOrEmpty()) {
                            if (rentType == 1){
                                lastPayType = 3
                            }
                            // 没有卡
                            showPreAuthSelectDialog(sno = sn)
                        } else {
                            // 有卡
                            if (rentType == 1){
                                lastPayType = 2
                            }
                            val cardEntity = it.cardList.last()
                            showPreAuthSelectDialog(sno = sn, cardEntity = cardEntity)
                        }
                    }
                }
            }

            override fun onNetError(code: Int, e: String?) {
                super.onNetError(code, e)
                dismissDialog()
                toastShow(e)
            }
        })
    }

    override fun initClickEvent() {
        mBinding.btnConfirm.setThrottleListener {
            val isChecked = mBinding.boxAgree.isChecked
            if (!isChecked)
                return@setThrottleListener
            snoNo?.let { sno ->
                //预授权 - 判断身份与授权状态
                isCheckPreStatus = true
                mViewModel.rentOrderPreAuth(RentalAuthRequest(rentType = null, scanUrl = sno, source = 1))
            }
        }
    }


    /**
     * 租借下单 - Google授权支付
     *
     * @param paymentMethodId Google payment token
     */
    private fun requestGoogleAuth(paymentMethodId: String) {
        mViewModel.rentOrderPreAuth(
            RentalAuthRequest(
                rentType = 2,
                paymentTokenObject = paymentMethodId,
                scanUrl = snoNo ?: "",
                source = 1
            )
        )
    }


    /**
     * 提示授权选择弹框
     *
     * @param sno 机柜编号
     */
    private fun showPreAuthSelectDialog(sno: String, cardEntity: CardEntity? = null) {
        preSelectDialog?.dismiss()
        preSelectDialog = WalletDialogUtil.instance.showPreAuthorizationSheet(this,
            googleReady = isGoogleReady,
            lastPayType = lastPayType,
            prepaymentAmount = prepaymentAmount,
            cardInfo = cardEntity,
            googlePayAction = {
                requestGooglePayment(preAuthAmount)
                DataAppManager.instance.saveLastPayType(1)
            },
            bankcardAction = {
                DataAppManager.instance.saveLastPayType(2)
                mViewModel.rentOrderPreAuth(
                    RentalAuthRequest(
                        rentType = 1,
                        scanUrl = sno,
                        source = 1,
                        bankcardId = cardEntity?.id
                    )
                )
            },
            addCardAction = {
                showSheetCardPay()
                DataAppManager.instance.saveLastPayType(3)
                preSelectDialog?.dismiss()
            },
            depositAction = {
                DataAppManager.instance.saveLastPayType(4)
                DataAppManager.instance.rentScanTag = true
                val depositIntent = Intent(this@RentPlanActivity, PaymentCodeActivity::class.java)
                depositIntent.putExtra(Extra.IT_TYPE, BisType.Bis_Prepayment)
                depositIntent.putExtra(Extra.IT_MONEY, prepaymentAmount)
                depositIntent.putExtra(Extra.IT_CODE, true)
                depositIntent.putExtra(Extra.IT_SNO, sno)
                mPaymentLauncher.launch(depositIntent)
                preSelectDialog?.dismiss()
            }
        )
    }


    /**
     * 支付交互
     * --使用新卡支付
     */
    private fun showSheetCardPay() {
        if (cardPayDialog?.isVisible == true) {
            cardPayDialog?.dismiss()
            cardPayDialog = null
        }
        cardPayDialog = SheetPaymentDialog(BisType.Bis_PreAuth, true, object : ICardPayListener {
            override fun onScanBankcard() {
                stripeScanSheet?.present()
            }

            override fun onPaymentByCard(param: CardParams, payParams: PaymentMethodCreateParams?, bind: Boolean, default: Boolean) {
                cardPayParams = payParams
                stripe?.createCardToken(param, callback = object : ApiResultCallback<Token> {
                    override fun onError(e: Exception) {
                        dismissDialog()
                        toastShow(e.message)
                    }

                    override fun onSuccess(result: Token) {
                        result.card?.let { card ->
                            val req = CardBindReq(
                                token = result.id,
                                bankNo = card.last4 ?: "",
                                bankExpire = StrUtil.setCardBindExp(card.expYear, card.expMonth),
                                bankName = card.brand.displayName,
                                bankType = card.funding?.name,
                                postalCode = card.addressZip,
                                defaulted = default,
                                save = bind
                            )
                            snoNo?.let { sno -> //直接输入信用卡预授权
                                mViewModel.rentOrderPreAuth(
                                    RentalAuthRequest(
                                        rentType = 1,
                                        scanUrl = sno,
                                        source = 1,
                                        bankcardInfo = req
                                    )
                                )
                            }
                        }
                    }
                })
            }
        })
        cardPayDialog?.show(supportFragmentManager, "SheetPaymentDialog")
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        //Stripe 处理前端支付或者前端检验结果
        stripe?.onPaymentResult(requestCode, data, object : ApiResultCallback<PaymentIntentResult> {
            override fun onError(e: Exception) {
                dismissDialog()
                val errorStripeTx = e.message ?: ""
                LogUtil.d("---Stripe status: $errorStripeTx")
                toastShow(errorStripeTx)
            }

            override fun onSuccess(result: PaymentIntentResult) {
                dismissDialog()
                if (cardPayDialog?.isVisible == true) {
                    cardPayDialog?.dismiss()
                    cardPayDialog = null
                }
                val paymentIntent = result.intent
                val status = paymentIntent.status
                LogUtil.d("---Stripe status: $status")
                if (status == StripeIntent.Status.RequiresCapture) {
                    startRentActivityByDirect()
                } else {
                    toastShow(("---Stripe status: $status"))
                }
            }
        })
    }


    /**
     * 支付 Google 前端支付
     *
     * @param money 支付金额
     */
    private fun requestGooglePayment(money: Double) {
        googleMethodLauncher?.startGooglePayment(
            currencyTx,
            amount = MathUtil.mul(money, 100.0).toInt()
        ) {
            //Loading action
            LogUtil.d("---Start Google Pay :$money")
        }
    }

    /**
     * 支付 Stripe前端检查
     *
     * @param clientSecret 支付秘钥
     */
    private fun requestAppPayment(
        clientSecret: String,
        params: PaymentMethodCreateParams? = null,
        showLoading: () -> Unit
    ) {
        showLoading()
        val confirmParams = params?.let {
            ConfirmPaymentIntentParams.createWithPaymentMethodCreateParams(it, clientSecret)
        } ?: ConfirmPaymentIntentParams.create(clientSecret)
        stripe?.confirmPayment(this, confirmParams)
    }

    //--------------------------------------授权逻辑-------------------------------------

    /**
     * 租借下单 - 押金下单逻辑
     *
     * @param sno 机柜编号
     */
    private fun requestRentOrder(sno: String) {
        hintCountShow = false
        mHandler.postDelayed({
            hintCountShow = true
            if (rentItSuccess) {
                startRentActivity() //网络接口成功-跳转页面
            }
        }, 2000L)
        mHandler.postDelayed({
            AppDialogUtil.instance.showRentingHintDialog(
                this,
                getString(R.string.rent_loading_hint)
            )
        }, 200L)
        rentItSuccess = false
        mViewModel.rentOrder(sno)
    }


    /**
     * 直接弹宝逻辑
     */
    private fun startRentActivityByDirect() {
        mHandler.postDelayed({
            startRentActivity()
        }, 2000L)
        mHandler.postDelayed({
            if (cardPayDialog?.isVisible == true) {
                cardPayDialog?.dismiss()
                cardPayDialog = null
            }
            AppDialogUtil.instance.showRentingHintDialog(
                this,
                getString(R.string.rent_loading_hint)
            )
        }, 200L)
    }

    /**进度条页面*/
    private fun startRentActivity() {
        AppDialogUtil.instance.cleanHintDialog()
        orderNo?.let {no->
            startActivity<RentOrderActivity>(Extra.IT_ORDERNO to no)
            overridePendingTransition(0, android.R.anim.slide_out_right)
            finish()
        }
    }

    override fun onDestroy() {
        if (null != cardPayDialog && cardPayDialog?.isVisible == true) {
            cardPayDialog?.dismiss()
        }
        if (null != preSelectDialog && preSelectDialog?.isShowing == true) {
            preSelectDialog?.dismiss()
        }
        super.onDestroy()
    }

    /**
     * 获取协议语言参数
     * 规则：中文(zh) -> cn，其他语言 -> vi（默认）
     */
    private fun getAgreementLangParam(): String {
        val languageCode = LanguageConfig.instance.getLanguageCode()
        return if (languageCode == Language.ZH) "cn" else "vi"
    }
}